package Beta;

import java.util.ArrayList;

import ClassificationAlgorithm.CollectiveClassificationAlgorithmClass;
import Definitions.GraphClass;
import Definitions.NodeClass;
import Global.ConstantVariable;
import Global.GlobalClass;
import Sampling.SamplingAbstractClass;
import Utility.WorkerUtilityClass;

public class LocalBetaCalculatorClass {
	
	GraphClass graph;
	GlobalClass global;
	
	public LocalBetaCalculatorClass(GraphClass graph, GlobalClass global)
	{
		this.graph = graph;
		this.global = global;
	}
	
	public void calculateLocalBetaForTheFoldWithTheSpecifiedEdgeTypes(ArrayList<CollectiveClassificationAlgorithmClass> classifierList, SamplingAbstractClass sampling) 
	{	
		int sizeOfTheClassifierList = classifierList.size();	
		ArrayList<NodeClass> nodeListToBeUsedForTest=sampling.getTestNodes();		
		ArrayList<NodeClass> nodeListToBeUsedForTrain=sampling.getTrainAndValNodes();
		CollectiveClassificationAlgorithmClass cca;		
		int edgeType = ConstantVariable.Common_ConstantVariables.DEFAULT_EDGE_TYPE;
		
		int neighbourhoodLevel;
		int neighbourhoodLevelForTheNeighboursOfTheNeighbours;
		
		double[][] localBetaMatrixForThisFold = new double[sizeOfTheClassifierList][nodeListToBeUsedForTest.size()];
		double[][] localBetaMatrixForTheWholeDataset;
		
		WorkerUtilityClass.initializeTwoDimensionalArray(localBetaMatrixForThisFold, 0);
		
		if(ConstantVariable.ExecutionParameters.outputRawResultsFiles)
		{
			localBetaMatrixForTheWholeDataset= new double[sizeOfTheClassifierList][graph.getDataSet().size()];
			WorkerUtilityClass.initializeTwoDimensionalArray(localBetaMatrixForTheWholeDataset, 0);
		}


		for(int i=0; i<sizeOfTheClassifierList;i++)
		{
			cca = classifierList.get(i);
								
			if(cca.getName()==ConstantVariable.CCA_ConstantVariables.CONTENT_ONLY)
			{
				edgeType = ConstantVariable.Common_ConstantVariables.DEFAULT_EDGE_TYPE_FOR_CONTENT_GRAPH;
				neighbourhoodLevel = ConstantVariable.AlphaRelated_ConstantVariables.DEFAULT_NEIGHBOURHOOD_LEVEL_FOR_CONTENT_BASED_LINKS;
				neighbourhoodLevelForTheNeighboursOfTheNeighbours = ConstantVariable.BetaRelated_ConstantVariables.DEFAULT_SECOND_ABSTRACT_NEIGHBOURHOOD_LEVEL_FOR_CONTENT_BASED_LINKS;
				 
				
			}
			else
			{
				neighbourhoodLevel = ConstantVariable.AlphaRelated_ConstantVariables.DEFAULT_NEIGHBOURHOOD_LEVEL_FOR_LINK_BASED_LINKS;
				neighbourhoodLevelForTheNeighboursOfTheNeighbours = ConstantVariable.BetaRelated_ConstantVariables.DEFAULT_SECOND_ABSTRACT_NEIGHBOURHOOD_LEVEL_FOR_LINK_BASED_LINKS;
			}
			
			int testNodeNo=0;
			
			int sifirKomsusuOlanSayisi = 0;
			
			for(NodeClass k : nodeListToBeUsedForTest)
			{				
				localBetaMatrixForThisFold[i][testNodeNo] = getHomophilyOfTheNodeForTheFoldUsingKnownNodes(k, edgeType, neighbourhoodLevel, neighbourhoodLevelForTheNeighboursOfTheNeighbours, sampling);
				if(ConstantVariable.ExecutionParameters.outputRawResultsFiles)
					localBetaMatrixForTheWholeDataset[i][k.getOrder()] = localBetaMatrixForThisFold[i][testNodeNo];
				testNodeNo++;
			}	
			
			if(ConstantVariable.ExecutionParameters.outputRawResultsFiles)
				for(NodeClass k : nodeListToBeUsedForTrain)
					localBetaMatrixForTheWholeDataset[i][k.getOrder()] = getHomophilyOfTheNodeForTheFoldUsingKnownNodes(k, edgeType, neighbourhoodLevel, neighbourhoodLevelForTheNeighboursOfTheNeighbours, sampling);;
			
			System.out.println("sifirKomsusuOlanSayisi:"+sifirKomsusuOlanSayisi);
			//System.out.println("enAzEsikKadarKomsusuOlanNodeSayisi("+i+")"+enAzEsikKadarKomsusuOlanNodeSayisi);
		
			Utility.WorkerUtilityClass.printSeperator();

		}
		
		System.out.println("Betalar hesaplandi:");
		
		//WorkerUtilityClass.printMatrix(localAlphaMatrixForThisFold, localAlphaMatrixForThisFold.length, localAlphaMatrixForThisFold[0].length, "Local Alpha Matrix");
		
		sampling.setLocalBetaMatrixForThisFold(localBetaMatrixForThisFold, localBetaMatrixForTheWholeDataset);	
		
		//alphaAndAccuracyCalculationCompletedEvent(graph, DirectoryStructureAndSettingsClass.getDatasetName());	
	}
	
	public double getHomophilyOfTheNodeForTheFoldUsingKnownNodes(NodeClass currentNode, int edgeType, int neighbourhoodLevel, int neighbourhoodLevelForTheNeighboursOfTheNeighbours, SamplingAbstractClass sampling)
	{
		ArrayList<NodeClass> knownNeighboursOfTheNode = sampling.getNeighboursOfTheNodeWrtStageInANotManner(currentNode, edgeType, neighbourhoodLevel, ConstantVariable.Sampling_Constants.NODE_IS_IN_TEST_SET_FOR_THE_FOLD);
		ArrayList<NodeClass> knownNeighboursOfTheNeighboursOfTheNode;
		
		int numberOfKnownNeighborsOfTheNode = knownNeighboursOfTheNode.size();
		int numberOfKnownNeighboursOfTheKnownNeighbours;
		int numberOfNeighboursHavingTheSameClass = 0;
				
		if(numberOfKnownNeighborsOfTheNode==0)
			return 0;
		
		int classLabelActualOfTheKnownNeighbourOfTheNode;
		
		double knownHomophilyOfTheKnownNeighbour;
		double sumOfTheKnownHomophiliesOfTheNeighbours = 0;
		
		//ArrayList<NodeClass> realNeighbourListOfTheNode;
		
		for(int i=0; i<numberOfKnownNeighborsOfTheNode; i++)
		{
			numberOfNeighboursHavingTheSameClass = 0;
			
			knownNeighboursOfTheNeighboursOfTheNode = sampling.getNeighboursOfTheNodeWrtStageInANotManner(knownNeighboursOfTheNode.get(i), edgeType, neighbourhoodLevelForTheNeighboursOfTheNeighbours, ConstantVariable.Sampling_Constants.NODE_IS_IN_TEST_SET_FOR_THE_FOLD);
			numberOfKnownNeighboursOfTheKnownNeighbours = knownNeighboursOfTheNeighboursOfTheNode.size();
			
			classLabelActualOfTheKnownNeighbourOfTheNode = knownNeighboursOfTheNode.get(i).getClassOrder();
			
			for(int j=0; j<numberOfKnownNeighboursOfTheKnownNeighbours; j++)
			{				
				if(classLabelActualOfTheKnownNeighbourOfTheNode == knownNeighboursOfTheNeighboursOfTheNode.get(j).getClassOrder())
				{
					numberOfNeighboursHavingTheSameClass++;				
				}
			}
			if(numberOfKnownNeighboursOfTheKnownNeighbours == 0)
				knownHomophilyOfTheKnownNeighbour = 0;
			else
			{
				knownHomophilyOfTheKnownNeighbour = (double)numberOfNeighboursHavingTheSameClass/numberOfKnownNeighboursOfTheKnownNeighbours;
				sumOfTheKnownHomophiliesOfTheNeighbours += knownHomophilyOfTheKnownNeighbour;
			}
			//AS_TEST_START
			//realNeighbourListOfTheNode = knownNeighboursOfTheNode.get(i).getNeighbours(edgeType, neighbourhoodLevel);
			//System.out.println("STATS:"+numberOfKnownNeighboursOfTheKnownNeighbours+"/"+realNeighbourListOfTheNode.size()+"):"+knownHomophilyOfTheKnownNeighbour+"_"+knownNeighboursOfTheNode.get(i).getHomophilyOfTheNode(edgeType, neighbourhoodLevel));
			//AS_TEST_END
		}		
		
		
		return (double)sumOfTheKnownHomophiliesOfTheNeighbours/numberOfKnownNeighborsOfTheNode;		
	}	
}
